In [1]:
import matplotlib.pyplot as plt
import numpy as np
from ipywidgets import interactive
from matplotlib import animation
from IPython.display import HTML
%matplotlib widget
First, we define a 2D lattice as follow:
In [2]:
# Define the position of the original lattice
x = np.linspace(0,6,7)
y = np.linspace(-3,3,7)
x_origine,y_origine = np.meshgrid(x,y)
Next, we define a function that updates the atomic positions in the lattice at each call
In [3]:
def interactive_wave_plot(k):
'''
:param k: wave number
'''
global current_k
current_k= k
# Define the position of the displaced lattice
x_p = x + np.sin(k*x)
x_long,y_long = np.meshgrid(x_p,y)
x_p = x + np.sin(k*x);
y_p = y + np.sin(k*(x-np.mean(x)))
x_trans=x_origine
y_trans = y_origine+np.sin(k*x)
fig1.clear();
fig1.set_xticks([]);
fig1.set_yticks([]);
fig1.axis([-1,7,-4.5,4.5]);
fig1.set_title('Transverse');
fig1.plot(x_origine,y_origine,'ko', mfc='none');
fig1.plot(x_trans,y_trans,'ko');
fig2.clear();
fig2.set_title('Longitudinal');
fig2.set_xticks([]);
fig2.set_yticks([]);
fig2.axis([-1,7,-4.5,4.5]);
fig2.plot(x_origine,y_origine,'ko', mfc='none');
fig2.plot(x_long,y_long,'ko');
In [4]:
fig, (fig1, fig2) = plt.subplots(1,2, figsize=(10,5)); # Initialize a figure
plt.ion();
interactive(interactive_wave_plot,k=(-1,1,0.01))
Out[4]:
interactive(children=(FloatSlider(value=0.0, description='k', max=1.0, min=-1.0, step=0.01), Output()), _dom_c…
Use similar function definition to make two animations, respectively, for longitudinal and transverse mode
In [5]:
fig_long = plt.figure()
ax = plt.axes()
ax.set_xlim((-1.5,7.5))
ax.set_ylim((-5,5))
line_or, = ax.plot([], [], 'ko',mfc=None)
line_mov, = ax.plot([], [], 'ko')
plt.title("Longitudinal")
ax.set_xticks([])
ax.set_yticks([])
# Initialization function: plot the background of each frame
def init_long():
line_or.set_data([], [])
line_mov.set_data([], [])
return line_or,
# Animation function which updates figure data. This is called sequentially
def animate_long(iteration):
global current_k
k=current_k
omega=3
t=omega*2*(1/100)/np.pi*iteration
x = np.linspace(0,6,7)
y = np.linspace(-3,3,7)
x_origine,y_origine = np.meshgrid(x,y)
# Define the position of the displaced lattice
x_p = x + np.sin(k*x-omega*t)
x_long,y_long = np.meshgrid(x_p,y)
x_trans=x_origine
y_trans = y_origine+np.sin(k*x-omega*t)
line_mov.set_data(np.asarray([x_long,y_long]))
return line_mov,
# Call the animator. blit=True means only re-draw the parts that have changed.
if 'anim_trans' in locals():
anim_trans.event_source.stop()
anim_long = animation.FuncAnimation(fig_long, animate_long, init_func=init_long,frames=112, interval=25, blit=True)
In [6]:
fig_trans = plt.figure()
ax_trans = plt.axes()
ax_trans.set_xlim((-1.5,7.5))
ax_trans.set_ylim((-5,5))
line_or, = ax_trans.plot([], [], 'ko',mfc=None)
line_mov, = ax_trans.plot([], [], 'ko')
plt.title("Transverse")
ax_trans.set_xticks([])
ax_trans.set_yticks([])
# Initialization function: plot the background of each frame
def init():
line_or.set_data([], [])
line_mov.set_data([], [])
return line_or,
# Animation function which updates figure data. This is called sequentially
def animate(iteration):
global current_k
k=current_k
omega=3
t=omega*2*(1/100)/np.pi*iteration
x_origine,y_origine = np.meshgrid(np.linspace(0,6,7),np.linspace(-3,3,7))
x_trans=x_origine
y_trans = y_origine+np.sin(k*x-omega*t)
line_mov.set_data(np.asarray([x_trans,y_trans]))
return line_mov,
# Call the animator. blit=True means only re-draw the parts that have changed.
if 'anim_long' in locals():
anim_long.event_source.stop()
anim_trans = animation.FuncAnimation(fig_trans, animate, init_func=init,frames=112, interval=25, blit=True)
In [ ]: